package org.micode.common.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class JsonUtils {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
            .setSerializationInclusion(JsonInclude.Include.NON_NULL);

    public static String toJson(Object obj) {
        if (obj == null) {
            return null;
        } else {
            try {
                return OBJECT_MAPPER.writeValueAsString(obj);
            } catch (Exception e) {
                log.error("Call JsonUtils.toJson() failed: {}", obj, e);
                return null;
            }
        }
    }

    public static <T> T toBean(String json, Class<T> classOfT) {
        return fromJson(json, classOfT);
    }

    public static <T> T fromJson(String json, Class<T> classOfT) {
        try {
            return OBJECT_MAPPER.readValue(json, classOfT);
        } catch (JsonProcessingException e) {
            log.error("Call JsonUtils.fromJson() failed: {}", json, e);
            return null;
        }
    }

    public static <T> T fromJsonFile(String fileName, Class<T> classOfT) {
        try {
            return OBJECT_MAPPER.readValue(new File(fileName), classOfT);
        } catch (Exception e) {
            log.error("Call JsonUtils.fromJsonFile() failed: {}", fileName, e);
            return null;
        }
    }

    public static <T> List<T> jsonToList(String json, Class<T> beanType) {
        if (null == json) {
            return null;
        }

        JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
        try {
            return OBJECT_MAPPER.readValue(json, javaType);
        } catch (Exception e) {
            log.error("Call JsonUtils.jsonToList() failed: {}", json, e);
        }

        return null;
    }

    public static <T, V> Map<T, V> jsonToMap(String json, Class<T> beanType1, Class<V> beanType2) {
        JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(Map.class, beanType1, beanType2);
        try {
            return OBJECT_MAPPER.readValue(json, javaType);
        } catch (Exception e) {
            log.error("Call JsonUtils.jsonToMap() failed: {}", json, e);
        }

        return null;
    }

    /**
     * @param json
     * @return
     * @Description:将json数据转换成JsonNode对象，可以获取子节点
     */
    public static JsonNode jsonToJsonNode(String json) {
        if (null == json) {
            return null;
        }

        JsonNode jsonNode;
        try {
            jsonNode = OBJECT_MAPPER.readTree(json);
            return jsonNode;
        } catch (Exception e) {
            log.error("Call JsonUtils.jsonToJsonNode() failed: {}", json, e);
            return null;
        }
    }

    /**
     * @param jsonNode
     * @param fieldName
     * @Description: 从jsonNode中获取某个字段的INT值
     * @return: 无论是null，还是空字符串，都返回null
     */
    public static Integer getIntValueFromField(JsonNode jsonNode, String fieldName) {
        String val = getValueFromField(jsonNode, fieldName);
        if (null != val) {
            try {
                return Integer.valueOf(val);
            } catch (Exception e) {
                log.warn("数据转换失败（String => Int）: {}", val);
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * @param jsonNode
     * @param fieldName
     * @Description: 从jsonNode中获取某个字段的Long值
     * @return: 无论是null，还是空字符串，都返回null
     */
    public static Long getLongValueFromField(JsonNode jsonNode, String fieldName) {
        String val = getValueFromField(jsonNode, fieldName);
        if (null != val) {
            try {
                return Long.valueOf(val);
            } catch (Exception e) {
                log.warn("数据转换失败（String => Long）: {}", val);
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * @param jsonNode
     * @param fieldName
     * @Description: 从jsonNode中获取某个字段的Long值
     * @return: 无论是null，还是空字符串，都返回null
     */
    public static Boolean getBooleanValueFromField(JsonNode jsonNode, String fieldName) {
        String val = getValueFromField(jsonNode, fieldName);
        if (null != val) {
            return "true".equals(val) || "T".equals(val) || "1".equals(val);
        } else {
            return false;
        }
    }

    /**
     * @param jsonNode
     * @param fieldName
     * @Description: 从jsonNode中获取某个字段的值
     * @return: 无论是null，还是空字符串，都返回null
     */
    public static String getValueFromField(JsonNode jsonNode, String fieldName) {
        if (null == jsonNode || null == fieldName) {
            return null;
        }

        JsonNode node = jsonNode.get(fieldName);
        if (node != null) {
            String textValue = node.asText();
            if ("".equals(textValue.trim())) {
                return null;
            } else {
                return textValue;
            }
        } else {
            return null;
        }
    }

    public static <T> T fromJsonByKey(String json, String key, Class<T> classOfKey) {
        Map<String, T> map = jsonToMap(json, String.class, classOfKey);
        if (null != map) {
            return getValueByKey(map, key, classOfKey);
        }

        return null;
    }

    public static <T> T getValueByKey(Map<String, T> jsonMap, String key, Class<T> classOfKey) {
        if (null == jsonMap) {
            return null;
        }

        for (String theKey : jsonMap.keySet()) {
            if (key.equalsIgnoreCase(theKey)) {
                return jsonMap.get(theKey);
            }
        }
        return null;
    }

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("queryDate", "2021-06-01");
        System.out.println(toJson(map));
    }
}